package com.jhy.ws.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.jhy.core.domain.R;
import com.jhy.core.enums.UserType;
import com.jhy.core.utils.Check;
import com.jhy.core.utils.redis.RedisUtils;
import com.jhy.ws.constants.WebSocketConstant;
import com.jhy.ws.domain.WsMsgRecord;
import com.jhy.ws.domain.bo.WsMsgRecordBo;
import com.jhy.ws.enums.EventTypeEnum;
import com.jhy.ws.factory.WebsocketTypeFactory;
import com.jhy.ws.mapper.WsMsgRecordMapper;
import com.jhy.ws.storage.WebSocketSessionStorage;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import javax.websocket.server.ServerEndpoint;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/websocket")
public class WebsocketHandler extends AbstractWebSocketHandler {

    private WsMsgRecordMapper recordMapper = SpringUtil.getBean(WsMsgRecordMapper.class);

    /**
     * 连接成功后调用
     * **/
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//        super.afterConnectionEstablished(session);
        String loginId = session.getAttributes().get("loginId").toString();
        String token = session.getAttributes().get("token").toString();
        String userName = session.getAttributes().get("userName").toString();
        Long userId = Long.valueOf(session.getAttributes().get("userId").toString());
        ConcurrentHashMap<String, WebSocketSession> sessionMap = WebSocketSessionStorage.SESSION_MAP;
        if (sessionMap.containsKey(loginId)) {
            sessionMap.get(loginId).close();
        }
        sessionMap.put(loginId, session);
        WsMsgRecordBo recordBo = new WsMsgRecordBo();
        recordBo.setFromUser(userName);
        recordBo.setFromUserId(userId);
        recordBo.setMsg("上线提醒");
        recordBo.setStorage(false);
        recordBo.setTargetType(UserType.SYS_USER.getUserType());
        recordBo.setEventType(EventTypeEnum.oline.getCode());
        RedisUtils.publish(WebSocketConstant.ONLINE_STATUS_QUEUE, recordBo);
    }

    /**
     * 处理消息
     * **/
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        super.handleMessage(session, message);
    }

    /**
     * 处理文本消息
     * **/
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//        super.handleTextMessage(session, message);
        String payload = message.getPayload();
        System.out.println(payload);
        if (Check.isNoEmpty(payload)){
            WsMsgRecordBo bean = JSONUtil.parse(payload).toBean(WsMsgRecordBo.class);
            bean.setSendTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
            WebsocketTypeFactory.instance(bean).sendMsg();
            recordMapper.insert(BeanUtil.toBean(bean, WsMsgRecord.class));
        }

    }

    /**
     * 处理二进制消息
     * **/
    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        super.handleBinaryMessage(session, message);
    }

    /**
     * 处理ping消息
     * **/
    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
        super.handlePongMessage(session, message);
    }

    /**
     * 处理传输错误
     * **/
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
    }

    /**
     * 连接关闭后调用
     * **/
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String loginId = session.getAttributes().get("loginId").toString();
        String token = session.getAttributes().get("token").toString();
        String userName = session.getAttributes().get("userName").toString();
        Long userId = Long.valueOf(session.getAttributes().get("userId").toString());
        WebSocketSessionStorage.SESSION_MAP.remove(loginId);
        WsMsgRecordBo recordBo = new WsMsgRecordBo();
        recordBo.setFromUser(userName);
        recordBo.setFromUserId(userId);
        recordBo.setMsg("下线提醒");
        recordBo.setStorage(false);
        recordBo.setTargetType(UserType.SYS_USER.getUserType());
        recordBo.setEventType(EventTypeEnum.logout.getCode());
        RedisUtils.publish(WebSocketConstant.ONLINE_STATUS_QUEUE, recordBo);
        super.afterConnectionClosed(session, status);
    }
}
